import json

from flask_wtf import FlaskForm
from flask_wtf.file import FileRequired, FileSize, FileAllowed
from wtforms.fields.numeric import IntegerField
from wtforms.fields.simple import StringField, FileField
from wtforms.validators import DataRequired, NumberRange, Optional
from marshmallow import Schema, fields, pre_dump

from src.entity.upload_entity import ALLOW_AUDIO_EXTENSION
from src.model import Exercise, category, Category, StudentAnswer, ExerciseUserMans, StudentUserAnswer, ExerciseUser
from src.model.exercises_main_model import ExerciseMans
from src.pkg.pageinator import PaginatorReq


class SubExercisesSchema(FlaskForm):
    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])




class AnswersSchema(FlaskForm):
    question = StringField('question', validators=[
        DataRequired("question参数不能为空")
    ])
    answer = StringField('answer', validators=[
        DataRequired("answer参数不能为空")
    ])
    user_answer = StringField('user_answer', validators=[
        DataRequired("user_answer参数不能为空")
    ])
    answer_id = StringField('answer_id', validators=[
        Optional()
    ])
    exercise_id = IntegerField('exercise_id', validators=[
        DataRequired("exercise_id参数不能为空")
    ])

    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
class GetSourcesSchema(PaginatorReq):
    start_date =  StringField('start_date', validators=[
       Optional()
    ])
    end_date =  StringField('end_date', validators=[
        Optional()
    ])
class CreeateCategorySchema(FlaskForm):
    question = StringField('question', validators=[
        DataRequired("question参数不能为空")
    ])

class CountSchema(FlaskForm):
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
class ErrorListSchema(PaginatorReq):
    status= StringField('status', validators=[
        DataRequired("status参数不能为空")
    ])
    # category_id: int, exercises_name: str
    category_id=StringField('category_id', validators=[Optional()])
    exercises_name = StringField('status', validators=[
        Optional()
    ])
class QuestionSchema(FlaskForm):
    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
class ScoreSchema(FlaskForm):
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
class CateGorySchema(FlaskForm):
    question = StringField('question', validators=[
        DataRequired("question参数不能为空")
    ])
class DeleteByIdMains(FlaskForm):
    id = IntegerField('id', validators=[
                                                          DataRequired("id不能为空")])
class QuestionSchemaSign(FlaskForm):


    exercise_id = IntegerField('exercise_id', validators=[NumberRange(min=0, message="exercise_id最小值是0"),
                                                          DataRequired("exercise_id不能为空")])
class UploadUrlSchema(FlaskForm):
    exercise_id = IntegerField('exercise_id', validators=[NumberRange(min=0, message="exercise_id最小值是0")])
class CategoryScoresSchema(FlaskForm):
    start_date = StringField('start_date', validators=[
       Optional()
    ])
    end_date =  StringField('end_date', validators=[
       Optional()
    ])

class AudioSchema(FlaskForm):
        file = FileField(
            "file",
            validators=[
                FileRequired("上传音频不能为空"),
                FileSize(max_size=15 * 1024 * 1024, message="音频大小不能超过15MB")
            ])
class ErrorReplaySchema(FlaskForm):
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
class ExitSchema(FlaskForm):
    branch_id = StringField('question', validators=[
        DataRequired("branch_id参数不能为空")
    ])
    exercise_id = IntegerField('exercise_id', validators=[NumberRange(min=0, message="exercise_id最小值是0"),
                                                          DataRequired("exercise_id不能为空")])
class UserCategory(FlaskForm):
    source = IntegerField('source', validators=[NumberRange(min=0, message="source最小值是0"),
                                                       ])
    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])

class TryExercisesSchema(FlaskForm):
    # difficulty: int, exercise_id: int,category_id:int
    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])

    exercise_id = IntegerField('exercise_id', validators=[NumberRange(min=0, message="exercise_id最小值是0"),
                                                          DataRequired("exercise_id不能为空")])
class TryUserExercisesSchema(FlaskForm):
    # difficulty: int, exercise_id: int,category_id:int
    category_id = IntegerField('category_id', validators=[NumberRange(min=0, message="category_id最小值是0"),
                                                          DataRequired("category_id不能为空")])

    exercise_id = IntegerField('exercise_id', validators=[NumberRange(min=0, message="exercise_id最小值是0"),
                                                          DataRequired("exercise_id不能为空")])
    source = StringField('source', validators=[DataRequired("source参数不能为空")])
    category_name =  StringField('category_name', validators=[DataRequired("类目名称不能为空")])
class ExercisesSchemaSelect(Schema):

    category_id = fields.Integer(dump_default=0)
    category_name= fields.String(dump_default="")
    compile = fields.Integer(dump_default=0)
    score=fields.Integer(dump_default=0)
    id=fields.Integer(default=0)
    branch_id = fields.String(dump_default="")
    user_id=fields.Integer(dump_default=0)
    created_at = fields.Integer(default=0)
    updated_at = fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: ExerciseMans, **kwargs):
        score=data.getScore
        return {
            "id":data.id,
            "category_id": data.category_id,
            "compile": data.compile,
            "score":score,
            "branch_id": data.branch_id,
            "user_id": data.user_id,
            "category_name":data.name,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp()),
        }

    class ExercisesSchemaSelect(Schema):
        category_id = fields.Integer(dump_default=0)
        category_name = fields.String(dump_default="")
        compile = fields.Integer(dump_default=0)
        score = fields.Integer(dump_default=0)
        branch_id = fields.String(dump_default="")
        user_id = fields.Integer(dump_default=0)
        created_at = fields.Integer(default=0)
        updated_at = fields.Integer(default=0)

        @pre_dump
        def process_data(self, data: ExerciseMans, **kwargs):
            score = data.getScore
            return {
                "category_id": data.category_id,
                "compile": data.compile,
                "score": score,
                "branch_id": data.branch_id,
                "user_id": data.user_id,
                "category_name": data.name,
                "created_at": int(data.created_at.timestamp()),
                "updated_at": int(data.updated_at.timestamp()),
            }
class ExercisesSchemaUserSelect(Schema):
        category_id = fields.Integer(dump_default=0)
        category_name = fields.String(dump_default="")
        compile = fields.Integer(dump_default=0)
        score = fields.Integer(dump_default=0)
        branch_id = fields.String(dump_default="")
        id = fields.Integer(default=0)
        user_id = fields.Integer(dump_default=0)
        created_at = fields.Integer(default=0)
        updated_at = fields.Integer(default=0)

        @pre_dump
        def process_data(self, data: ExerciseUserMans, **kwargs):
            score = data.getScore
            return {
                "category_id": data.category_id,
                "compile": data.compile,
                "id":data.id,
                "score": score,
                "branch_id": data.branch_id,
                "user_id": data.user_id,
                "category_name": data.name,
                "created_at": int(data.created_at.timestamp()),
                "updated_at": int(data.updated_at.timestamp()),
            }


class CateGorySchemaRsp(Schema):
    name=fields.String(dump_default="")
    id=fields.Integer(dump_default=0)
    @pre_dump
    def process_data(self, data: category, **kwargs):
        return {
            "name":data.name,
            "id":data.id
        }
class CountSourcesSchemaRsp(Schema):
    category_id = fields.Integer(dump_default=0)
    category_name=fields.String(dump_default="")
    source=fields.Integer(dump_default=0)
    branch_id=fields.String(dump_default="")
    user_id=fields.Integer(dump_default=0)
    created_at = fields.Integer(default=0)
    updated_at = fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: StudentAnswer, **kwargs):
        return {
            "category_id": data.category_id,
            "category_name":data.getCateGoryName,
            "branch_id":data.branch_id,
            "source":data.getSource,
            "user_id":data.user_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp()),
        }



class ExercisesSchema(Schema):
    exercise_id= fields.Integer(dump_default=0)
    subject= fields.String(dump_default="")
    user_id= fields.Integer(dump_default=0)
    category_id=fields.Integer(dump_default=0)
    category_name=fields.String(dump_default="")
    question_text= fields.String(dump_default="")
    answer_text= fields.String(dump_default="")
    categorys = fields.List(fields.Dict(dump_default={}), dump_default=[])
    compile= fields.Integer(dump_default=0)
    score=fields.Integer(default=0)
    branch_id= fields.String(dump_default="")
    created_at= fields.Integer(default=0)
    updated_at= fields.Integer(default=0)
    total_count=fields.Integer(default=0)
    count= fields.Integer(default=0)
    @pre_dump
    def process_data(self, data: Exercise, **kwargs):
        print(data.getCount)
        return {
            "exercise_id": data.exercise_id,
            "subject": data.subject,
            "category_name":data.getCatgory.name,
            "user_id": data.user_id,
            "total_count":data.getTotalCount,
            "count":data.getCount,
            "score":data.score,
            "categorys":data.similarit_category,
            "category_id": data.category_id,
            "question_text":  json.loads(data.question_text),
            "answer_text": json.loads(data.answer_result),
            "compile": data.compile,
            "branch_id": data.branch_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp()),
        }


class ExercisesUserSchema(Schema):
    exercise_id= fields.Integer(dump_default=0)
    subject= fields.String(dump_default="")
    user_id= fields.Integer(dump_default=0)
    category_id=fields.Integer(dump_default=0)
    question_text= fields.String(dump_default="")
    answer_text= fields.String(dump_default="")
    categorys = fields.List(fields.Dict(dump_default={}), dump_default=[])
    compile= fields.Integer(dump_default=0)
    score=fields.Integer(default=0)
    branch_id= fields.String(dump_default="")
    created_at= fields.Integer(default=0)
    category_name= fields.String(dump_default="")
    source_value= fields.String(dump_default="")
    updated_at= fields.Integer(default=0)
    total_count=fields.Integer(default=0)
    count= fields.Integer(default=0)
    @pre_dump
    def process_data(self, data: ExerciseUser, **kwargs):
        print(data)
        return {
            "exercise_id": data.exercise_id,
            "subject": data.subject,
            "user_id": data.user_id,
            "total_count":data.getTotalCount,
            "count":data.getCount,
            "score":data.score,
            "category_name":data.getCatgory.name,
            "source_value":data.getCatgory.source,
            "categorys":data.similarit_category,
            "category_id": data.category_id,
            "question_text":  json.loads(data.question_text),
            "answer_text": json.loads(data.answer_result),
            "compile": data.compile,
            "branch_id": data.branch_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp()),
        }

class ExercisesSignSchema(Schema):
    exercise_id= fields.Integer(dump_default=0)
    subject= fields.String(dump_default="")
    user_id= fields.Integer(dump_default=0)
    category_id=fields.Integer(dump_default=0)
    question_text= fields.String(dump_default="")
    answer_text= fields.String(dump_default="")
    categorys = fields.List(fields.Dict(dump_default={}), dump_default=[])
    compile= fields.Integer(dump_default=0)
    score=fields.Integer(default=0)
    branch_id= fields.String(dump_default="")
    created_at= fields.Integer(default=0)
    updated_at= fields.Integer(default=0)
    total_count=fields.Integer(default=0)
    count= fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: Exercise, **kwargs):
        answers=data.student_answers
        return {
            "exercise_id": data.exercise_id,
            "subject": data.subject,
            "user_id": data.user_id,
            "total_count": data.getTotalCount,
            "count": data.getCount,
            "categorys": data.similarit_category,
            "score": data.score,
            "category_id": data.category_id,
            "question_text": json.loads(data.question_text),
            "answer_text": json.loads(data.answer_result),
            "compile": data.compile,
            "branch_id": data.branch_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp()),
        }

class ExercisesUserSignSchema(Schema):
        exercise_id = fields.Integer(dump_default=0)
        subject = fields.String(dump_default="")
        user_id = fields.Integer(dump_default=0)
        category_id = fields.Integer(dump_default=0)
        question_text = fields.String(dump_default="")
        answer_text = fields.String(dump_default="")
        categorys = fields.List(fields.Dict(dump_default={}), dump_default=[])
        compile = fields.Integer(dump_default=0)
        score = fields.Integer(default=0)
        branch_id = fields.String(dump_default="")
        source_value = fields.String(dump_default="")
        category_name = fields.String(dump_default="")
        created_at = fields.Integer(default=0)
        updated_at = fields.Integer(default=0)
        total_count = fields.Integer(default=0)
        count = fields.Integer(default=0)

        @pre_dump
        def process_data(self, data: ExerciseUser, **kwargs):
            return {
                "exercise_id": data.exercise_id,
                "subject": data.subject,
                "user_id": data.user_id,
                "total_count": data.getTotalCount,
                "count": data.getCount,
                "source_value":data.getCatgory.source,
                "category_name": data.getCatgory.name,
                "categorys": data.similarit_category,
                "score": data.score,
                "category_id": data.category_id,
                "question_text": json.loads(data.question_text),
                "answer_text": json.loads(data.answer_result),
                "compile": data.compile,
                "branch_id": data.branch_id,
                "created_at": int(data.created_at.timestamp()),
                "updated_at": int(data.updated_at.timestamp()),
            }
class AnswerErrorSchemRsp(Schema):


    user_answer = fields.String(dump_default="")
    question_text=fields.String(dump_default="")
    answer_text=fields.String(dump_default="")
    answer_id=fields.Integer(dump_default=0)
    branch_id=fields.String(dump_default="")
    category_id=fields.Integer(dump_default=0)
    is_correct= fields.Boolean(dump_default=False)
    created_at = fields.Integer(default=0)
    updated_at = fields.Integer(default=0)
    @pre_dump
    def  process_data(self, data: StudentAnswer, **kwargs):
        return {
            "total":data.getTotalCount,
            "question_text": json.loads(data.getExercie_question_text),
            "answer_text":json.loads(data.answer_result),
            "answer_id": data.answer_id,
            "branch_id": data.branch_id,
            "category_id": data.category_id,
            "user_answer": json.loads(data.user_answer),
            "is_correct": data.is_correct,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp())
        }


class AnswersSchemaRsp(Schema):
    detailed_proof=fields.List(fields.String)
    is_correct=fields.String(dump_default="")
    key_knowledge=fields.List(fields.String)
    branch_id=fields.String(dump_default="")
    exercise_id=fields.Integer(dump_default=0)
    category_id=fields.Integer(dump_default=0)
    solution_idea=fields.String(dump_default="")
    exercise_text=fields.String(dump_default="")
    user_answer=fields.String(dump_default="")
    category_name=fields.String(dump_default="")
    id=fields.Integer(dump_default=0)
    answer_result=fields.String(dump_default="")
    created_at = fields.Integer(default=0)
    updated_at = fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: StudentAnswer, **kwargs):
        exercise = data.get_exercise_id
        return {
            "detailed_proof":json.loads(data.detailed_proof),
            "is_correct":data.is_correct,
            "branch_id":data.branch_id,
            "exercise_text":json.loads(exercise.question_text),
            "exercise_id":data.exercise_id,
            "category_id":data.category_id,
            "category_name":data.getCateGoryName,
            "answer_result":json.loads(data.answer_result),
            "user_answer":json.loads(data.user_answer),
            "key_knowledge":json.loads(data.key_knowledge),
            "solution_idea":json.loads(data.solution_idea),
            "id":data.answer_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp())
        }

class AnswersUserSchemaRsp(Schema):
    detailed_proof=fields.List(fields.String)
    is_correct=fields.String(dump_default="")
    key_knowledge=fields.List(fields.String)
    branch_id=fields.String(dump_default="")
    exercise_id=fields.Integer(dump_default=0)
    category_id=fields.Integer(dump_default=0)
    solution_idea=fields.String(dump_default="")
    exercise_text=fields.String(dump_default="")
    user_answer=fields.String(dump_default="")
    category_name=fields.String(dump_default="")
    id=fields.Integer(dump_default=0)
    answer_result=fields.String(dump_default="")
    created_at = fields.Integer(default=0)
    updated_at = fields.Integer(default=0)

    @pre_dump
    def process_data(self, data: StudentUserAnswer, **kwargs):
        exercise = data.get_exercise_id
        print(json.loads(exercise.question_text))
        print("zzzzzzzzzzzzzzzzzzzzzz")
        return {
            "detailed_proof":json.loads(data.detailed_proof),
            "is_correct":data.is_correct,
            "branch_id":data.branch_id,
            "exercise_text":json.loads(exercise.question_text),
            "exercise_id":data.exercise_id,
            "category_id":data.category_id,
            "category_name":data.getCateGoryName,
            "answer_result":json.loads(data.answer_result),
            "user_answer":json.loads(data.user_answer),
            "key_knowledge":json.loads(data.key_knowledge),
            "solution_idea":json.loads(data.solution_idea),
            "id":data.answer_id,
            "created_at": int(data.created_at.timestamp()),
            "updated_at": int(data.updated_at.timestamp())
        }
